package com.snow.component;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import com.snow.exception.CommonRuntimeException;
import com.snow.starter.SnowAutoConfiguration;
import io.minio.*;
import io.minio.errors.*;
import io.minio.http.Method;
import lombok.extern.slf4j.Slf4j;
import okhttp3.OkHttpClient;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Date;

@Slf4j
@ConditionalOnProperty(value = "snow.file-storage-type", havingValue = "minio", matchIfMissing = true)
@Component
public class MinioStorageComponent implements IStorageComponent {


    final SnowAutoConfiguration snowAutoConfiguration;
    final MinioClient minioClient;

    public MinioStorageComponent(SnowAutoConfiguration snowAutoConfiguration) {
        log.info("文件存储模式：minio");
        this.snowAutoConfiguration = snowAutoConfiguration;
        this.minioClient = MinioClient.builder()
                .endpoint(snowAutoConfiguration.getMinioEndpoint())
                .credentials(snowAutoConfiguration.getMinioAccessKey(), snowAutoConfiguration.getMinioSecretKey())
                .build();

    }


    @Override
    public String getPreviewUrl(String savePath) {
        if (savePath.startsWith("/" + snowAutoConfiguration.getPublicBucket())) {
            return snowAutoConfiguration.getMinioPreviewPrefix() + savePath;
        }
        try {
            String objectUrl = minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
                    .method(Method.GET)
                    .bucket(snowAutoConfiguration.getBucketName())
                    .extraQueryParams(MapUtil.of("response-content-type", FileUtil.getMimeType(savePath)))
                    .object(savePath.substring(snowAutoConfiguration.getBucketName().length() + 2))
                    .build());
            if (StrUtil.isBlank(snowAutoConfiguration.getMinioPreviewPrefix())) {
                return objectUrl;
            }
            return objectUrl.replace(snowAutoConfiguration.getMinioEndpoint(), snowAutoConfiguration.getMinioPreviewPrefix());
        } catch (Exception e) {
            throw new CommonRuntimeException("文件预览失败：" + e.getMessage());
        }
    }

    @Override
    public String save(InputStream fileInputStream, String fileName, boolean isPublic) {
        File tempFile = FileUtil.createTempFile();
        FileUtil.writeFromStream(fileInputStream, tempFile);
        String savePath = DateUtil.format(new Date(), "/yyyy/MM/dd/") + RandomUtil.randomString(6) + fileName.substring(fileName.lastIndexOf('.'));
        String bucketName = isPublic ? snowAutoConfiguration.getPublicBucket() : snowAutoConfiguration.getBucketName();
        try {
            if (!minioClient.bucketExists(BucketExistsArgs.builder().bucket(snowAutoConfiguration.getBucketName()).build())) {
                minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
            }
            minioClient.uploadObject(UploadObjectArgs.builder()
                    .bucket(bucketName)
                    .object(savePath)
                    .contentType(FileUtil.getMimeType(fileName))
                    .filename(tempFile.getAbsolutePath())
                    .build());
        } catch (Exception e) {
            throw new CommonRuntimeException("文件上传失败：" + e.getMessage());
        }
        return "/" + bucketName + savePath;
    }

    @Override
    public InputStream getObject(String objectName) {
        try {
            minioClient.getObject(GetObjectArgs.builder()
                    .bucket(snowAutoConfiguration.getBucketName())
                    .object(objectName)
                    .build());
        } catch (Exception e) {
            throw new CommonRuntimeException("文件加载失败：" + e.getMessage());
        }
        return null;
    }
}
